#include <iostream>
#include <string>
#include <string.h>
#include <functional>
#include "Log.hpp"
#include "InetAddr.hpp"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
using namespace LogModule;
class serve
{
public:
    using Handler = std::function<std::string(const std::string &, InetAddr &)>; // 定义一个function类型

    serve(uint16_t port, Handler handler)
        : _port(port),
          _is_runing(true), _handler(handler)
    {
    }

    // 初始化服务器
    bool Init()
    {
        // 创建套接字文件
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_sockfd == -1)
        {
            LOG(FATAL) << "套接字创建失败";
            return false;
        }

        else
            LOG(INFO) << "套接字创建成功，文件描述符为: " << _sockfd;

        // 填充sockaddr_in结构体
        struct sockaddr_in local;
        bzero(&local, sizeof(local)); // 将local字段置空
        local.sin_family = AF_INET;
        // ip和端口都需要先转为网络序列
        local.sin_port = htons(_port);
        local.sin_addr.s_addr = INADDR_ANY; // 监听所有可用的网络接口（0,0,0,0)

        // 绑定本地套接字至文件
        int n = bind(_sockfd, (struct sockaddr *)(&local), sizeof(local));
        if (n == -1)
        {
            LOG(FATAL) << "绑定失败";
            return false;
        }
        return true;
    }

    // 启动服务器
    void Start()
    {
        while (_is_runing)
        {
            // 收消息
            char buffer[1024];
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            ssize_t s = recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (sockaddr *)(&peer), &len);
            if (s > 0)
            {
                InetAddr client(peer); // 封装客户端信息
                buffer[s] = 0;
                // 发送经过上层处理后的消息（回调函数)
                const std::string result = _handler(buffer, client); // 发送给服务器上层收到的客户端消息以及客户端本身的ip信息
                ssize_t n = sendto(_sockfd, result.c_str(), result.length(), 0, (sockaddr *)(&peer), len);
            }
        }
    }
    ~serve() {}

private:
    int _sockfd;      // 文件描述
    uint16_t _port;   // 端口号
    bool _is_runing;  // 服务器状态
    Handler _handler; // 消息处理器
};